use std::sync::Arc;

use lazy_static::lazy_static;
use redb::{TableDefinition, TableError};
use ruma::{OwnedRoomId, OwnedServerName, RoomId, UserId};

use crate::{Result, DATABASE};

pub struct Service {}

lazy_static! {
    pub static ref SERVICE: Arc<Service> = Service::build();
}

const UESRID_JOINED_ROOMS_DEFINITION: TableDefinition<&str, Vec<String>> =
    TableDefinition::new("user_joined_rooms");

impl Service {
    pub fn build() -> Arc<Self> {
        Arc::new(Self {})
    }

    pub fn room_servers(&self, room_id: &RoomId) -> Result<Vec<OwnedServerName>> {
        unimplemented!()
    }

    pub fn joined_rooms(&self, user_id: &UserId) -> Result<Vec<OwnedRoomId>> {
        let db = &DATABASE;
        let read_ctx = db.begin_read().map_err(redb::Error::from)?;
        let rooms_table = match read_ctx.open_table(UESRID_JOINED_ROOMS_DEFINITION) {
            Err(TableError::TableDoesNotExist(_)) => {
                return Ok(vec![]);
            }
            res => res,
        }
        .map_err(redb::Error::from)?;
        let res = rooms_table
            .get(&user_id.as_str())
            .map_err(redb::Error::from)?;
        let res = res.map(|x| x.value()).unwrap_or_default();
        Ok(res.iter().map(|x| RoomId::parse(x).unwrap()).collect())
    }
}
